/**
 * 
 */
package edu.ou.cs.youming.services;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;

import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.jaxb.UnmarshallerProperties;
import org.eclipse.persistence.oxm.MediaType;

/**
 * @author Youming Lin
 * 
 */
public class JAXBService {
	/**
	 * Parses a file to an object of specified class.
	 * 
	 * @param file
	 * @param cls
	 * @param type
	 * @param includeRoot
	 * @return
	 * @throws JAXBException
	 * @throws FileNotFoundException
	 */
	public static final <T> T read(final File file, final Class<T> cls,
			final MediaType type, final boolean includeRoot) throws JAXBException,
			FileNotFoundException {
		if (file == null) {
			throw new NullPointerException("file");
		}

		if (cls == null) {
			throw new NullPointerException("class");
		}

		if (type == null) {
			throw new NullPointerException("media type");
		}

		final JAXBContext jc = JAXBContext.newInstance(cls);
		final Unmarshaller unmarshaller = jc.createUnmarshaller();
		final StreamSource source = new StreamSource(new FileReader(file));

		unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, type);
		unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, includeRoot);

		final JAXBElement<T> jaxbElement = unmarshaller.unmarshal(source, cls);

		return jaxbElement.getValue();
	}

	/**
	 * Writes the specified object to specified file.
	 * 
	 * @param obj
	 * @param file
	 * @param type
	 * @param includeRoot
	 * @throws JAXBException
	 * @throws FileNotFoundException
	 */
	public static final <T> void write(final T obj, final File file,
			final MediaType type, final boolean includeRoot) throws JAXBException,
			FileNotFoundException {
		if (file == null) {
			throw new NullPointerException("file");
		}

		if (type == null) {
			throw new NullPointerException("media type");
		}

		final JAXBContext jc = JAXBContext.newInstance(obj.getClass());
		final Marshaller marshaller = jc.createMarshaller();

		marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, type);
		marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, includeRoot);
		marshaller.marshal(obj, file);
	}
}